package com.micro.ai.auth.aspect;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.micro.ai.auth.annotation.AuditLogAnnotation;
import com.micro.ai.auth.entity.AuditLog;
import com.micro.ai.auth.service.AuditLogService;
import com.micro.ai.commons.util.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import jakarta.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.UUID;

/**
 * 审计日志AOP切面
 * 
 * @author micro-ai
 * @since 0.0.1
 */
@Slf4j
@Aspect
@Component
public class AuditLogAspect {

    @Autowired
    private AuditLogService auditLogService;

    @Autowired
    private JwtUtils jwtUtils;

    @Autowired
    private ObjectMapper objectMapper;

    @Around("@annotation(auditLog)")
    public Object around(ProceedingJoinPoint joinPoint, AuditLogAnnotation auditLog) throws Throwable {
        AuditLog auditLogEntity = new AuditLog();
        
        try {
            // 获取请求信息
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            if (attributes != null) {
                HttpServletRequest request = attributes.getRequest();
                auditLogEntity.setMethod(request.getMethod());
                auditLogEntity.setUrl(request.getRequestURL().toString());
                auditLogEntity.setIpAddress(getClientIpAddress(request));
                auditLogEntity.setUserAgent(request.getHeader("User-Agent"));
            }

            // 获取方法信息
            //MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            //Method method = signature.getMethod();
            
            // 设置基本信息
            auditLogEntity.setId(UUID.randomUUID().toString().replace("-", ""));
            auditLogEntity.setAction(auditLog.action());
            auditLogEntity.setResourceType(auditLog.resourceType());
            auditLogEntity.setDescription(auditLog.description());
            auditLogEntity.setCreatedAt(LocalDateTime.now());
            //auditLogEntity.setMethod(method.getName());

            // 尝试从JWT token中获取用户信息
            try {
                String token = getTokenFromRequest();
                if (token != null) {
                    auditLogEntity.setUserId(jwtUtils.getUserId(token));
                    auditLogEntity.setTenantId(jwtUtils.getTenantId(token));
                }
            } catch (Exception e) {
                log.debug("无法从token获取用户信息: {}", e.getMessage());
            }

            // 记录请求参数
            if (auditLog.recordParams()) {
                Object[] args = joinPoint.getArgs();
                if (args.length > 0) {
                    // 过滤掉HttpServletRequest等不可序列化的对象
                    Object[] serializableArgs = Arrays.stream(args)
                            .filter(arg -> !(arg instanceof HttpServletRequest) && 
                                         !(arg instanceof jakarta.servlet.http.HttpServletResponse) &&
                                         !(arg instanceof jakarta.servlet.http.HttpSession))
                            .toArray();
                    if (serializableArgs.length > 0) {
                        auditLogEntity.setRequestParams(objectMapper.writeValueAsString(serializableArgs));
                    }
                }
            }

            // 执行方法
            Object result = joinPoint.proceed();

            // 记录响应状态
            auditLogEntity.setResponseStatus(200);

            // 记录响应结果
            if (auditLog.recordResult() && result != null) {
                auditLogEntity.setNewValue(objectMapper.writeValueAsString(result));
            }

            return result;

        } catch (Exception e) {
            auditLogEntity.setResponseStatus(500);
            auditLogEntity.setDescription(auditLog.description() + " - 执行失败: " + e.getMessage());
            throw e;
        } finally {
            // 异步记录审计日志
            try {
                auditLogService.recordAuditLog(auditLogEntity);
            } catch (Exception e) {
                log.error("记录审计日志失败: {}", e.getMessage(), e);
            }
        }
    }

    /**
     * 获取客户端IP地址
     */
    private String getClientIpAddress(HttpServletRequest request) {
        String xForwardedFor = request.getHeader("X-Forwarded-For");
        if (xForwardedFor != null && !xForwardedFor.isEmpty() && !"unknown".equalsIgnoreCase(xForwardedFor)) {
            return xForwardedFor.split(",")[0].trim();
        }
        
        String xRealIp = request.getHeader("X-Real-IP");
        if (xRealIp != null && !xRealIp.isEmpty() && !"unknown".equalsIgnoreCase(xRealIp)) {
            return xRealIp;
        }
        
        return request.getRemoteAddr();
    }

    /**
     * 从请求中获取token
     */
    private String getTokenFromRequest() {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (attributes != null) {
            HttpServletRequest request = attributes.getRequest();
            String authorization = request.getHeader("Authorization");
            if (authorization != null && authorization.startsWith("Bearer ")) {
                return authorization.substring(7);
            }
        }
        return null;
    }
}
